package com.hutra.utils {
        
	/**
	 * 
	 * @author hungconcon
	 */
	public class ArrayUtilities {
	
	
		public function ArrayUtilities() {
		}
		/**
		 * 
		 * @param	array
		 */
		public static function clearArray(array:Array):void { 
			for (var i:int = 0; i < array.length; i++) { 
				delete array.splice(i, 1); 
			}
			if (array.length > 0) {
				clearArray(array);
			}
		}
		/**
		 * Sync keep client data JSON to Object 
		 * @param	vo
		 * @param	object
		 * @return
		 */  
		public static function synchronizeValueObject(vo:*, object:Object = null):* {
			if (object == null) return null;
			for (var key:String in object) {
				try {
					if (object[key] == 'true') {
						vo[key] = true;
					}else if (object[key] == 'false') {
						vo[key] = false;
					}else if (object[key] != undefined || object[key] != '') {
						if (typeof vo[key] == 'boolean') {
							if (object[key] == 'false') {
								vo[key]	= false;
							}
							if (object[key] == '0') {
								vo[key]	= false;
							}
							if (object[key] == 'true') {
								vo[key]	= false;
							}
							if (object[key] == '1') {
								vo[key]	= true;
							}
						}else if (typeof vo[key] == 'object') {
							vo[key]	= object[key];
						}else if (typeof vo[key] == 'number') {
							vo[key] = Number(object[key]);
						} else {
							vo[key] = String(object[key]);
						}
					}else {
					}
				}catch (ex:Error) {
				}
			}
			return vo;
		}
		/**
		 * 
		 * @param	lastlist, the list is originality
		 * @param	index	
		 * @param	joinlist, the list you want to join
		 * @return
		 */
		public static function joinArray(lastlist:Array, index:int, joinlist:Array ):Array {
			if (index == -1 || (index >= lastlist.length)) {
				lastlist = lastlist.concat(joinlist);
			} else  if (index == 0) {
				lastlist = joinlist.concat(lastlist);
			} else {
				var a:Array  = lastlist.splice(index); 		//...8,9]
				var b:Array  = lastlist.splice(0, index);	//[1,2,3,....
				var c:Array  = b.concat(joinlist);			//[1,2,3,    |4,5,6,7|     ,8,9]
				lastlist 	 = c.concat(a);					//[1,2,3,4,5,6,7,8,9]
			}		
			return lastlist;
		}
		public static function insertObject( array:Array, index:int, value:Object ):Array {
			var original:Array;
			if ((index == -1) || (index > array.length)) {
				array.push(value);
				original = array;
			}else if (index == 0) {
				original = [value].concat(array.splice(index));
			}else {
				var a:Array  = array.splice(index);
				var b:Array  = array.splice(0, index).push(value);
				original = b.concat(a);
			}			
			return original;			
		}
		public static function removeAt( array:Array, index:uint ):Array {
			delete array.splice(index, 1);
			return array;
		}
		public static function moveObject(list:Array, from:int, to:int):Array{
			// from is the element you wish to move
			// to is the position you want to insert it
			var temp:Array = list.splice(from, 1);
			list.splice(to, 0, temp[0]);
			return  list;
		}
		public static function swapList(list:Array, from:Number, to:Number):Array {
		  var a:Object = list[from];
		  var b:Object = list[to];
		  list.splice(from, 1, b);
		  list.splice(to, 1, a);
		  return list;
		}
		public static function randomize(a:Array):Array {
		  var aCopy:Array = a.concat();
		  var aRandomized:Array = new Array();
		  var oElement:Object;
		  var nRandom:Number;
		  for(var i:Number = 0; i < aCopy.length; i++) {
			nRandom = NumberUtilities.random(0, aCopy.length - 1);
			aRandomized.push(aCopy[nRandom]);
			aCopy.splice(nRandom, 1);
			i--;
		  }
		  return aRandomized;
		}

		public static function average(a:Array):Number {
		  return sum(a) / a.length;
		}

		public static function sum(a:Array):Number {
		  var nSum:Number = 0;
		  for(var i:Number = 0; i < a.length; i++) {
			if(typeof a[i] == "number") {
			  nSum += a[i];
			}
		  }
		  return nSum;
		}

		public static function max(a:Array):Number {
		  var aCopy:Array = a.concat();
		  aCopy.sort(Array.NUMERIC);
		  var nMaximum:Number = Number(aCopy.pop());
		  return nMaximum;
		}

		public static function min(a:Array):Number {
		  var aCopy:Array = a.concat();
		  aCopy.sort(Array.NUMERIC);
		  var nMinimum:Number = Number(aCopy.shift());
		  return nMinimum;
		}
		

		private static function objectEquals(oInstanceA:Object, oInstanceB:Object):Boolean {
		  for(var sItem:String in oInstanceA) {
			if(oInstanceA[sItem] is Object) {
			  if(!objectEquals(oInstanceA[sItem], oInstanceB[sItem])) {
				return false;
			  }
			}
			else {
			  if(oInstanceA[sItem] != oInstanceB[sItem]) {
				return false;
			  }
			}
		  }
		  return true;
		}

		public static function equals(aA:Array, aB:Array, bNotOrdered:Boolean, bRecursive:Boolean):Boolean {
		  if(aA.length != aB.length) {
			return false;
		  }
		  var aACopy:Array = aA.concat();
		  var aBCopy:Array = aB.concat();
		  if(bNotOrdered) {
			aACopy.sort();
			aBCopy.sort();
		  }
		  for(var i:Number = 0; i < aACopy.length; i++) {
			if(aACopy[i] is Array && bRecursive) {
			  if(!equals(aACopy[i], aBCopy[i], bNotOrdered, bRecursive)) {
				return false;
			  }
			}
			else if(aACopy[i] is Object && bRecursive) {
			  if(!objectEquals(aACopy[i], aBCopy[i])) {
				return false;
			  }
			}
			else if(aACopy[i] != aBCopy[i]) {
			  return false;
			}
		  }
		  return true;
		}

		public static function findMatchIndex(a:Array, oElement:Object, ...rest):Number {
		  var nStartingIndex:Number = 0;
		  var bPartialMatch:Boolean = false;
		  if(typeof rest[0] == "number") {
			nStartingIndex = rest[0];
		  }    
		  else if(typeof rest[1] == "number") {
			nStartingIndex = rest[1];
		  }
		  if(typeof rest[0] == "boolean") {
			bPartialMatch = rest[0];
		  }
		  var bMatch:Boolean = false;
		  for(var i:Number = nStartingIndex; i < a.length; i++) {
			if(bPartialMatch) {
			  bMatch = (a[i].indexOf(oElement) != -1);
			}
			else {
			  bMatch = (a[i] == oElement);
			}
			if(bMatch) {
			  return i;
			}
		  }
		  return -1;
		}

		public static function findLastMatchIndex(a:Array, oElement:Object, oParameter:Object):Number {
		  var nStartingIndex:Number = a.length;
		  var bPartialMatch:Boolean = false;
		  if(typeof arguments[2] == "number") {
			nStartingIndex = arguments[2];
		  }    
		  else if(typeof arguments[3] == "number") {
			nStartingIndex = arguments[3];
		  }
		  if(typeof arguments[2] == "boolean") {
			bPartialMatch = arguments[2];
		  }
		  var bMatch:Boolean = false;
		  for(var i:Number = nStartingIndex; i >= 0; i--) {
			if(bPartialMatch) {
			  bMatch = (a[i].indexOf(oElement) != -1);
			}
			else {
			  bMatch = (a[i] == oElement);
			}
			if(bMatch) {
			  return i;
			}
		  }
		  return -1;
		}

		public static function findMatchIndices(a:Array, oElement:Object, bPartialMatch:Boolean = false):Array {
		  var aIndices:Array = new Array();
		  var nIndex:Number = findMatchIndex(a, oElement, bPartialMatch);
		  while(nIndex != -1) {
			aIndices.push(nIndex);
			nIndex = findMatchIndex(a, oElement, bPartialMatch, nIndex + 1);
		  }
		  return aIndices;
		}

		public static function duplicate(oArray:Object, bRecursive:Boolean = false):Object {
		  var oDuplicate:Object;
		  if(bRecursive) {
			if(oArray is Array) {
			  oDuplicate = new Array();
			  for(var i:Number = 0; i < oArray.length; i++) {
				if(oArray[i] is Object) {
				  oDuplicate[i] = duplicate(oArray[i]);
				}
				else {
				  oDuplicate[i] = oArray[i];
				}
			  }
			  return oDuplicate;
			}
			else {
			  oDuplicate = new Object();
			  for(var sItem:String in oArray) {
				if(oArray[sItem] is Object && !(oArray[sItem] is String) && !(oArray[sItem] is Boolean) && !(oArray[sItem] is Number)) {
				  oDuplicate[sItem] = duplicate(oArray[sItem], bRecursive);
				}
				else {
				  oDuplicate[sItem] = oArray[sItem];
				}
			  }
			  return oDuplicate;
			}
		  }
		  else {
			if(oArray is Array) {
			  return oArray.concat();
			}
			else {
			  oDuplicate = new Object();
			  for(var sstem:String in oArray) {
				oDuplicate[sstem] = oArray[sstem];
			  }
			  return oDuplicate;
			}
		  }
		}

		static public function toString(oArray:Object, nLevel:uint = 0):String {
			 var sIndent:String = "";
			 for(var i:Number = 0; i < nLevel; i++) {
			sIndent += "\t";
			 }
			 var sOutput:String = "";
			 for(var sItem:String in oArray) {
			if(oArray[sItem] is Object) {
			  sOutput = sIndent + "** " + sItem + " **\n" + toString(oArray[sItem], nLevel + 1) + sOutput;
			}
			else {
			  sOutput += sIndent + sItem + ":" + oArray[sItem] + "\n";
			}
			 }
			 return sOutput;
			}
		}
}